
#ifndef _TTG_SERVICES_TIMER_
#define _TTG_SERVICES_TIMER_
#include "Common/Definitions.h"

#include "Common/Math.h"
#include "Runtime.Low/Threads.h"
#include "Runtime.Low/Services/Service.h"
#include "Runtime.Low/Services/Logger/Logger.h"

#include "UpdaterThread.h"

namespace ttg
{
	namespace services
	{
		//Represents High-Resolution timer.
		class Timer :public Service
		{
			private:
				static Timer *ref;
			private:
				threads::Clock *clock;
				ttg_internal::services::UpdaterThread *updater;
			protected:
				//Starts HighRes timer.
				//If hardware doesn't support such timers, throws Error.
				virtual void startUnSafe(std::vector<Service *> &deps, const char *params);
				virtual void stopUnSafe();
			public:
				Timer();
				//Returns abstract time in milliseconds.
				//Note: according to MSDN, this method can return diffrent results on diffrent CPU cores.
				//So be afraid!
				DWORD getTime();
				//Returns abstract time in milliseconds.
				//Should be used for time interval measuring only.
				double getMilliSeconds();
				//Returns abstract time in seconds.
				//Should be used for time interval measuring only.
				double getSeconds();
				//Sets notifier, that will call loopback after required time.
				//Note: for delegate creattion use make_delegate().
				math::uint64 setNotifier(
					    ttg::structures::Delegate<void, double> *loopback,
						double rate,
						bool is_continual = false,
						bool is_disabled = false);
				//Enables notifier. It will not be ignored.
				void enableNotifier(math::uint64 ID)
				{ updater->enableEvent(ID); }
				//Disables notifier. It will be ignored.
				void disableNotifier(math::uint64 ID)
				{ updater->disableEvent(ID); }
				//Returns reference to the instance (which always exists).
				inline static Timer *getRef()
				{ return ref == NULL ? (ref = new Timer()) : ref; }
		};
	}
}

#endif
